#include <stdio.h>
#include <stdlib.h>

typedef enum { false, true } bool;

typedef int Vertex; /* 顶点编号类型 */
#define kMaxVertex 1000  /* 最大顶点数   */

typedef struct VCNode *VertexCover; /* 顶点覆盖集 */
struct VCNode {
    Vertex *ver; /* 存储顶点的数组 */
    int size; /* 集合规模 */
};

typedef struct EdgeNode *Edges; /* 图中的边 */
struct EdgeNode {
    Vertex u, v; /* 边的两个端点 */
};

typedef struct EdgeSetNode *EdgeSet; /* 边集合 */
struct EdgeSetNode {
    Edges e; /* 存储边的数组 */
    int size; /* 集合规模 */
};

EdgeSet InitEdgeSet(int m) {
    /* 初始化一个空的边集合，最大容量为m */
    EdgeSet E;

    E = (EdgeSet)malloc(sizeof(struct EdgeSetNode));
    E->e = (Edges)malloc(sizeof(struct EdgeNode) * m);
    E->size = 0;
    return E;
}

VertexCover InitSet() {
    /* 初始化一个空的顶点覆盖集合 */
    VertexCover C;
    int i;

    C = (VertexCover)malloc(sizeof(struct VCNode));
    C->size = 0;
    C->ver = (Vertex *)malloc(sizeof(Vertex) * kMaxVertex);

    return C;
}

void Insert(VertexCover C, Vertex u, Vertex v) {
    /* 将顶点u和v插入顶点覆盖集合C */
    C->ver[C->size] = u;
    C->size++;
    C->ver[C->size] = v;
    C->size++;
}

void Delete(EdgeSet E, Vertex u, Vertex v) {
    /* 从边集合E中删除所有跟顶点u和v相连的边 */
    int i, last;

    for (i = 0; i < E->size; i++) { /* 检查E中每一条边 */
        if (E->e[i].u == u || E->e[i].u == v || E->e[i].v == u
        || E->e[i].v == v) { /* 找到应该删除的边 */
            last = E->size - 1; /* 最后一条边的位置 */
            if (last != i) {
                E->e[i] = E->e[last]; /* 用最后一条边填补删除第i条边后的空缺 */
                i--; /* 下一轮循环i++后应该检查刚填补进来的这条边 */
            } /* 如果last=i，则删除的是最后一条边 */
            E->size--;
        }
    }
}

/* 算法16-1：顶点覆盖问题的近似算法 VertexCoverApproximation(E) */
VertexCover VertexCoverApproximation(EdgeSet E) {
    VertexCover C;
    Vertex u, v;
    int i;

    C = InitSet(); /* 顶点覆盖集合初始化为空 */
    while (E->size > 0) {
        u = E->e[0].u; /* 从E中任意选取一条边(u, v) */
        v = E->e[0].v;
        Insert(C, u, v); /* 将顶点u和 v插入顶点覆盖集合 */
        Delete(E, u, v); /* 从E中删除以顶点u或顶点v为端点的所有边 */
    }
    return C;
}
/* 算法16-1 结束 */

int main(void) {
    EdgeSet E;
    VertexCover C;
    Vertex u, v;
    int m, i;

    scanf("%d", &m);
    E = InitEdgeSet(m);
    for (i = 0; i < m; i++) {
        scanf("%d %d", &u, &v);
        E->e[E->size].u = u;
        E->e[E->size].v = v;
        E->size++;
    }
    C = VertexCoverApproximation(E);
    for (i = 0; i < C->size; i++) {
        printf("%d ", C->ver[i]);
    }

    return 0;
}